{% extends "base.html" %}

{% block title %}聚类分析 - SurveyAnalyzer{% endblock %}

{% block breadcrumb %}
<nav aria-label="breadcrumb">
    <ol class="breadcrumb">
        <li class="breadcrumb-item">
            <a href="{{ url_for('main.index') }}">
                <i class="fas fa-home me-1"></i>
                首页
            </a>
        </li>
        <li class="breadcrumb-item active" aria-current="page">
            <i class="fas fa-project-diagram me-1"></i>
            聚类分析
        </li>
    </ol>
</nav>
{% endblock %}

{% block content %}
<div class="row">
    <!-- 聚类配置 -->
    <div class="col-md-4 mb-4">
        <div class="card">
            <div class="card-header">
                <h6 class="mb-0">
                    <i class="fas fa-cogs me-2"></i>
                    聚类配置
                </h6>
            </div>
            <div class="card-body">
                <div class="mb-3">
                    <label for="algorithm" class="form-label">聚类算法</label>
                    <select class="form-select" id="algorithm">
                        <option value="kmeans">K-Means 聚类</option>
                        <option value="dbscan">DBSCAN 聚类</option>
                        <option value="hierarchical">层次聚类</option>
                        <option value="spectral">谱聚类</option>
                    </select>
                    <div class="form-text">选择适合您数据的聚类算法</div>
                </div>
                
                <div class="mb-3">
                    <label for="nClusters" class="form-label">聚类数量</label>
                    <input type="number" class="form-control" id="nClusters" value="3" min="2" max="20">
                    <div class="form-text">建议选择2-10个聚类</div>
                </div>
                
                <div class="mb-3">
                    <label class="form-label">特征选择</label>
                    <div id="featureSelection">
                        <!-- 特征选择将在这里动态生成 -->
                    </div>
                </div>
                
                <button class="btn btn-primary" onclick="startClustering()">
                    <i class="fas fa-play me-1"></i>
                    开始聚类
                </button>
            </div>
        </div>
        
        <!-- 聚类质量评估 -->
        <div class="card mt-3" id="qualityCard" style="display: none;">
            <div class="card-header">
                <h6 class="mb-0">
                    <i class="fas fa-star me-2"></i>
                    聚类质量
                </h6>
            </div>
            <div class="card-body">
                <div id="qualityMetrics">
                    <!-- 质量指标将在这里显示 -->
                </div>
            </div>
        </div>
    </div>
    
    <!-- 聚类结果 -->
    <div class="col-md-8">
        <div class="card">
            <div class="card-header d-flex justify-content-between align-items-center">
                <h5 class="mb-0">
                    <i class="fas fa-chart-scatter me-2"></i>
                    聚类结果
                </h5>
                <div>
                    <button class="btn btn-outline-primary btn-sm" onclick="downloadResults()" id="downloadBtn" style="display: none;">
                        <i class="fas fa-download me-1"></i>
                        下载结果
                    </button>
                </div>
            </div>
            <div class="card-body">
                <div id="clusterChart" style="height: 400px;">
                    <div class="d-flex align-items-center justify-content-center h-100 text-muted">
                        <div class="text-center">
                            <i class="fas fa-project-diagram fa-3x mb-3"></i>
                            <p>配置聚类参数并点击"开始聚类"查看结果</p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        
        <!-- 聚类统计 -->
        <div class="card mt-3" id="statsCard" style="display: none;">
            <div class="card-header">
                <h6 class="mb-0">
                    <i class="fas fa-chart-bar me-2"></i>
                    聚类统计
                </h6>
            </div>
            <div class="card-body">
                <div id="clusterStats">
                    <!-- 聚类统计将在这里显示 -->
                </div>
            </div>
        </div>
    </div>
</div>

<!-- 聚类详情模态框 -->
<div class="modal fade" id="clusterDetailModal" tabindex="-1">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">
                    <i class="fas fa-info-circle me-2"></i>
                    聚类详情
                </h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
            </div>
            <div class="modal-body">
                <div id="clusterDetailContent">
                    <!-- 聚类详情内容 -->
                </div>
            </div>
        </div>
    </div>
</div>

<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<script>
let currentData = null;
let clusterResults = null;
const filename = '{{ filename }}';

// 页面加载时获取数据信息
document.addEventListener('DOMContentLoaded', function() {
    loadDataInfo();
});

function loadDataInfo() {
    fetch(`/api/data/${filename}`)
        .then(response => response.json())
        .then(data => {
            currentData = data;
            generateFeatureSelection(data.numeric_columns);
        })
        .catch(error => {
            console.error('加载数据信息失败:', error);
        });
}

function generateFeatureSelection(numericColumns) {
    const container = document.getElementById('featureSelection');
    
    if (numericColumns.length === 0) {
        container.innerHTML = '<p class="text-muted">没有可用的数值特征</p>';
        return;
    }
    
    let html = '';
    numericColumns.forEach(column => {
        html += `
            <div class="form-check">
                <input class="form-check-input" type="checkbox" value="${column}" id="feature_${column}" checked>
                <label class="form-check-label" for="feature_${column}">
                    ${column}
                </label>
            </div>
        `;
    });
    
    container.innerHTML = html;
}

function getSelectedFeatures() {
    const checkboxes = document.querySelectorAll('#featureSelection input[type="checkbox"]:checked');
    return Array.from(checkboxes).map(cb => cb.value);
}

function startClustering() {
    const selectedFeatures = getSelectedFeatures();
    
    if (selectedFeatures.length < 2) {
        alert('请至少选择两个特征进行聚类分析');
        return;
    }
    
    const algorithm = document.getElementById('algorithm').value;
    const nClusters = parseInt(document.getElementById('nClusters').value);
    
    // 对于DBSCAN算法，聚类数量是自动确定的
    if (algorithm === 'dbscan' && nClusters) {
        // 这些算法不需要预设聚类数量
    } else if (nClusters < 2 || nClusters > 20) {
        alert('聚类数量必须在2-20之间');
        return;
    }
    
    const clusterData = {
        algorithm: algorithm,
        features: selectedFeatures,
        n_clusters: nClusters
    };
    
    // 显示加载状态
    document.getElementById('clusterChart').innerHTML = `
        <div class="d-flex align-items-center justify-content-center h-100">
            <div class="text-center">
                <div class="spinner-border text-primary" role="status">
                    <span class="visually-hidden">聚类分析中...</span>
                </div>
                <p class="mt-2">正在进行聚类分析，请稍候...</p>
            </div>
        </div>
    `;
    
    fetch(`/api/cluster/${filename}`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(clusterData)
    })
    .then(response => {
        if (!response.ok) {
            throw new Error(`HTTP ${response.status}: ${response.statusText}`);
        }
        return response.json();
    })
    .then(data => {
        if (data.error) {
            document.getElementById('clusterChart').innerHTML = `
                <div class="alert alert-danger">
                    <i class="fas fa-exclamation-triangle me-2"></i>
                    聚类分析失败：${data.error}
                </div>
            `;
        } else {
            clusterResults = data;
            displayClusterResults(data);
        }
    })
    .catch(error => {
        console.error('聚类分析错误:', error);
        document.getElementById('clusterChart').innerHTML = `
            <div class="alert alert-danger">
                <i class="fas fa-exclamation-triangle me-2"></i>
                聚类分析失败：${error.message || '网络请求失败'}
            </div>
        `;
    });
}

function displayClusterResults(results) {
    // 清除加载状态
    const chartContainer = document.getElementById('clusterChart');
    chartContainer.innerHTML = ''; // 明确清空容器内容
    
    // 显示聚类图表
    if (results.visualization_data && results.visualization_data.coordinates) {
        const vizData = results.visualization_data;
        const coordinates = vizData.coordinates;
        const labels = vizData.labels;
        
        // 按聚类标签分组数据
        const clusters = {};
        coordinates.forEach((coord, index) => {
            const label = labels[index];
            if (!clusters[label]) {
                clusters[label] = {
                    x: [],
                    y: [],
                    name: label === -1 ? '噪声点' : `聚类 ${label}`,
                    mode: 'markers',
                    type: 'scatter',
                    marker: {
                        size: label === -1 ? 6 : 8,
                        opacity: label === -1 ? 0.5 : 0.7,
                        color: label === -1 ? 'gray' : undefined
                    }
                };
            }
            clusters[label].x.push(coord[0]);
            clusters[label].y.push(coord[1]);
        });
        
        const plotData = Object.values(clusters);
        // 获取算法名称映射
        const algorithmNames = {
            'kmeans': 'K-Means',
            'dbscan': 'DBSCAN',
            'hierarchical': '层次聚类',
            'spectral': '谱聚类'
        };
        
        const algorithmName = algorithmNames[results.algorithm] || results.algorithm;
        
        const layout = {
            title: `${algorithmName} 聚类结果 (${vizData.method}降维)`,
            xaxis: { title: '第一主成分' },
            yaxis: { title: '第二主成分' },
            showlegend: true,
            hovermode: 'closest'
        };
        
        Plotly.newPlot('clusterChart', plotData, layout, {responsive: true});
    } else {
        document.getElementById('clusterChart').innerHTML = `
            <div class="alert alert-warning">
                <i class="fas fa-exclamation-triangle me-2"></i>
                无法生成可视化图表：缺少可视化数据
            </div>
        `;
    }
    
    // 显示质量指标
    if (results.evaluation_metrics) {
        displayQualityMetrics(results.evaluation_metrics);
    }
    
    // 显示聚类统计
    if (results.cluster_profiles) {
        displayClusterStats(results.cluster_profiles);
    }
    
    // 显示下载按钮
    document.getElementById('downloadBtn').style.display = 'inline-block';
}

function displayQualityMetrics(metrics) {
    const container = document.getElementById('qualityMetrics');
    
    let html = '';
    for (const [key, value] of Object.entries(metrics)) {
        const displayName = {
            'silhouette_score': '轮廓系数',
            'calinski_harabasz_score': 'CH指数',
            'davies_bouldin_score': 'DB指数'
        }[key] || key;
        
        html += `
            <div class="mb-2">
                <div class="d-flex justify-content-between">
                    <span>${displayName}:</span>
                    <strong>${typeof value === 'number' ? value.toFixed(3) : value}</strong>
                </div>
            </div>
        `;
    }
    
    container.innerHTML = html;
    document.getElementById('qualityCard').style.display = 'block';
}

function displayClusterStats(profiles) {
    const container = document.getElementById('clusterStats');
    
    let html = '<div class="row">';
    
    // cluster_profiles是一个对象，键为cluster_0, cluster_1等或noise
    Object.entries(profiles).forEach(([clusterKey, cluster]) => {
        const displayName = clusterKey === 'noise' ? '噪声点' : clusterKey.replace('cluster_', '聚类 ');
        const cardClass = clusterKey === 'noise' ? 'border-secondary' : 'border-primary';
        const headerClass = clusterKey === 'noise' ? 'bg-secondary' : 'bg-primary';
        
        html += `
            <div class="col-md-4 mb-3">
                <div class="card ${cardClass}">
                    <div class="card-header ${headerClass} text-white">
                        <h6 class="mb-0">${displayName}</h6>
                    </div>
                    <div class="card-body">
                        <p><strong>样本数:</strong> ${cluster.size}</p>
                        <p><strong>占比:</strong> ${cluster.percentage.toFixed(1)}%</p>
                        <button class="btn btn-outline-primary btn-sm" onclick="showClusterDetail('${clusterKey}')">
                            <i class="fas fa-info me-1"></i>
                            查看详情
                        </button>
                    </div>
                </div>
            </div>
        `;
    });
    
    html += '</div>';
    container.innerHTML = html;
    document.getElementById('statsCard').style.display = 'block';
}

function showClusterDetail(clusterKey) {
    const cluster = clusterResults.cluster_profiles[clusterKey];
    const displayName = clusterKey === 'noise' ? '噪声点' : clusterKey.replace('cluster_', '聚类 ');
    
    let html = `
        <h6>${displayName} 详细信息</h6>
        <div class="row">
            <div class="col-md-6">
                <h6>基本信息</h6>
                <ul>
                    <li>样本数量: ${cluster.size}</li>
                    <li>占总体比例: ${cluster.percentage.toFixed(1)}%</li>
                </ul>
            </div>
            <div class="col-md-6">
                <h6>特征中心</h6>
                <ul>
    `;
    
    if (cluster.center) {
        for (const [feature, value] of Object.entries(cluster.center)) {
            html += `<li>${feature}: ${typeof value === 'number' ? value.toFixed(3) : value}</li>`;
        }
    }
    
    html += `
                </ul>
            </div>
        </div>
    `;
    
    // 如果有统计信息，也显示出来
    if (cluster.statistics && Object.keys(cluster.statistics).length > 0) {
        html += `
            <div class="row mt-3">
                <div class="col-12">
                    <h6>特征统计</h6>
                    <div class="table-responsive">
                        <table class="table table-sm">
                            <thead>
                                <tr>
                                    <th>特征</th>
                                    <th>均值</th>
                                    <th>标准差</th>
                                    <th>最小值</th>
                                    <th>最大值</th>
                                </tr>
                            </thead>
                            <tbody>
        `;
        
        for (const [feature, stats] of Object.entries(cluster.statistics)) {
            html += `
                <tr>
                    <td>${feature}</td>
                    <td>${stats.mean.toFixed(3)}</td>
                    <td>${stats.std.toFixed(3)}</td>
                    <td>${stats.min.toFixed(3)}</td>
                    <td>${stats.max.toFixed(3)}</td>
                </tr>
            `;
        }
        
        html += `
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        `;
    }
    
    document.getElementById('clusterDetailContent').innerHTML = html;
    new bootstrap.Modal(document.getElementById('clusterDetailModal')).show();
}

function downloadResults() {
    if (clusterResults) {
        const dataStr = JSON.stringify(clusterResults, null, 2);
        const dataBlob = new Blob([dataStr], {type: 'application/json'});
        
        const link = document.createElement('a');
        link.href = URL.createObjectURL(dataBlob);
        link.download = `cluster_results_${new Date().getTime()}.json`;
        link.click();
    }
}
</script>
{% endblock %}